package com.yc.spring.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

@Component
@Aspect  // 切面类 = 切点 + 增强
public class MyAspect {

    // 起点
    @Pointcut("execution(* com.yc..*.get*(..))")
    // * com..bean.*.get*(..)
    public void pointcut1(){}


    // 前置增强: 业务方法执行前, 进行增强
    //@Before("execution(* com.yc..*.get*(..))")
    @Before("pointcut1()")
    public void before(JoinPoint jp){
        System.out.println("前置增强: " + jp.getSignature());
    }

    @After("execution(* com.yc..*.set*(..))")
    public void after(JoinPoint joinPoint){
        System.out.println("后置增强: " + joinPoint.getSignature());
    }

    /**
     * @param joinPoint
     * @param ret       业务方法的返回结果
     *                  returning = "ret" 指定接收返回值的参数名称
     *
     *  DI => 依赖注入 => 注入的方式:
     *                  1. setter
     *                  2. 构造方法
     *                  3. 接口注入   Object ret
     */
    @AfterReturning(pointcut = "execution(* com.yc..*.*et*(..))",
        returning = "ret")
    public void returning(JoinPoint joinPoint, Object ret){
        System.out.println("返回增强: " + joinPoint.getSignature());
        System.out.println("返回增强: " + ret);
    }

    @AfterThrowing(pointcut = "execution(* com.yc..*.add(..))",
        throwing = "t")
    public void throwing(JoinPoint joinPoint, Throwable t){
        System.out.println("异常增强: " + joinPoint.getSignature());
        System.out.println("异常增强: " + t);
    }

    // 后置增强: 业务方法执行后, 不管正常还是异常,都执行
    // 返回增强: 业务方法执行后, 正常执行的到返回结果
    // 异常增强: 业务方法出现异常
    // 环绕增强

    /**
     * try{
     *     前置增强
     *     业务方法(拦截的方法)
     *     返回增强
     * } catch {
     *     异常增强
     * } finally {
     *     后置增强
     * }
     *
     */

    @Pointcut("execution(* com.yc..*.sub(..))")
    public void pointcut2(){}
    @Around("pointcut2()")
    public Object around(ProceedingJoinPoint pjp){
        // ProceedingJoinPoint 是 JoinPoint 的子类
        // 环绕增强的业务方法必须自己执行
        // 环绕增强方法的返回值, 就是业务方法的返回值
        try {
            long begin = System.currentTimeMillis();
            Object ret = pjp.proceed();
            long end = System.currentTimeMillis();
            System.out.println(pjp.getSignature() + "共耗时 " + (end - begin) + " 毫秒");
            return ret;
        } catch (Throwable throwable) {
            throw new RuntimeException(throwable);
        }
    }
















}
